package com.cencat.route.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cencat.common.result.Result;
import com.cencat.route.entity.Dispatch;
import com.cencat.route.service.DispatchService;
import com.cencat.route.vo.DispatchQueryVO;
import com.cencat.route.vo.DispatchStatisticsVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 调度管理控制器
 * 
 * @author cencat
 * @since 2024-01-01
 */
@Slf4j
@RestController
@RequestMapping("/api/route/dispatch")
@RequiredArgsConstructor
@Tag(name = "调度管理", description = "调度信息的增删改查和业务操作")
public class DispatchController {

    private final DispatchService dispatchService;

    @GetMapping("/page")
    @Operation(summary = "分页查询调度", description = "根据条件分页查询调度信息")
    public Result<Page<Dispatch>> getDispatchPage(
            @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Long current,
            @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") Long size,
            @Parameter(description = "查询条件") DispatchQueryVO query) {
        try {
            Page<Dispatch> page = new Page<>(current, size);
            Page<Dispatch> result = dispatchService.selectDispatchPage(page, query);
            return Result.success(result);
        } catch (Exception e) {
            log.error("分页查询调度失败: {}", e.getMessage(), e);
            return Result.error("分页查询调度失败: " + e.getMessage());
        }
    }

    @GetMapping("/list")
    @Operation(summary = "查询调度列表", description = "根据条件查询调度列表")
    public Result<List<Dispatch>> getDispatchList(@Parameter(description = "查询条件") DispatchQueryVO query) {
        try {
            List<Dispatch> result = dispatchService.selectDispatchList(query);
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询调度列表失败: {}", e.getMessage(), e);
            return Result.error("查询调度列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/{id}")
    @Operation(summary = "根据ID查询调度", description = "根据调度ID查询详细信息")
    public Result<Dispatch> getDispatchById(@Parameter(description = "调度ID") @PathVariable Long id) {
        try {
            Dispatch dispatch = dispatchService.getById(id);
            if (dispatch == null) {
                return Result.error("调度不存在");
            }
            return Result.success(dispatch);
        } catch (Exception e) {
            log.error("查询调度详情失败: {}", e.getMessage(), e);
            return Result.error("查询调度详情失败: " + e.getMessage());
        }
    }

    @PostMapping
    @Operation(summary = "新增调度", description = "创建新的调度信息")
    public Result<Boolean> createDispatch(@Parameter(description = "调度信息") @Valid @RequestBody Dispatch dispatch) {
        try {
            boolean result = dispatchService.save(dispatch);
            return result ? Result.success(true) : Result.error("新增调度失败");
        } catch (Exception e) {
            log.error("新增调度失败: {}", e.getMessage(), e);
            return Result.error("新增调度失败: " + e.getMessage());
        }
    }

    @PutMapping
    @Operation(summary = "更新调度", description = "更新调度信息")
    public Result<Boolean> updateDispatch(@Parameter(description = "调度信息") @Valid @RequestBody Dispatch dispatch) {
        try {
            boolean result = dispatchService.updateById(dispatch);
            return result ? Result.success(true) : Result.error("更新调度失败");
        } catch (Exception e) {
            log.error("更新调度失败: {}", e.getMessage(), e);
            return Result.error("更新调度失败: " + e.getMessage());
        }
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除调度", description = "根据ID删除调度")
    public Result<Boolean> deleteDispatch(@Parameter(description = "调度ID") @PathVariable Long id) {
        try {
            boolean result = dispatchService.removeById(id);
            return result ? Result.success(true) : Result.error("删除调度失败");
        } catch (Exception e) {
            log.error("删除调度失败: {}", e.getMessage(), e);
            return Result.error("删除调度失败: " + e.getMessage());
        }
    }

    @PutMapping("/batch/status")
    @Operation(summary = "批量更新调度状态", description = "批量更新调度状态")
    public Result<Boolean> batchUpdateDispatchStatus(
            @Parameter(description = "调度ID列表") @RequestBody List<Long> ids,
            @Parameter(description = "状态") @RequestParam String status,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = dispatchService.batchUpdateDispatchStatus(ids, status, updatedBy);
            return result ? Result.success(true) : Result.error("批量更新调度状态失败");
        } catch (Exception e) {
            log.error("批量更新调度状态失败: {}", e.getMessage(), e);
            return Result.error("批量更新调度状态失败: " + e.getMessage());
        }
    }

    @PutMapping("/batch/priority")
    @Operation(summary = "批量更新优先级", description = "批量更新调度优先级")
    public Result<Boolean> batchUpdatePriority(
            @Parameter(description = "调度ID列表") @RequestBody List<Long> ids,
            @Parameter(description = "优先级") @RequestParam Integer priority,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = dispatchService.batchUpdatePriority(ids, priority, updatedBy);
            return result ? Result.success(true) : Result.error("批量更新优先级失败");
        } catch (Exception e) {
            log.error("批量更新优先级失败: {}", e.getMessage(), e);
            return Result.error("批量更新优先级失败: " + e.getMessage());
        }
    }

    @PutMapping("/batch/assign-driver")
    @Operation(summary = "批量分配司机", description = "批量为调度分配司机")
    public Result<Boolean> batchAssignDriver(
            @Parameter(description = "调度ID列表") @RequestBody List<Long> ids,
            @Parameter(description = "司机ID") @RequestParam Long driverId,
            @Parameter(description = "分配人ID") @RequestParam Long assignedBy) {
        try {
            boolean result = dispatchService.batchAssignDriver(ids, driverId, assignedBy);
            return result ? Result.success(true) : Result.error("批量分配司机失败");
        } catch (Exception e) {
            log.error("批量分配司机失败: {}", e.getMessage(), e);
            return Result.error("批量分配司机失败: " + e.getMessage());
        }
    }

    @PutMapping("/batch/assign-vehicle")
    @Operation(summary = "批量分配车辆", description = "批量为调度分配车辆")
    public Result<Boolean> batchAssignVehicle(
            @Parameter(description = "调度ID列表") @RequestBody List<Long> ids,
            @Parameter(description = "车辆ID") @RequestParam Long vehicleId,
            @Parameter(description = "分配人ID") @RequestParam Long assignedBy) {
        try {
            boolean result = dispatchService.batchAssignVehicle(ids, vehicleId, assignedBy);
            return result ? Result.success(true) : Result.error("批量分配车辆失败");
        } catch (Exception e) {
            log.error("批量分配车辆失败: {}", e.getMessage(), e);
            return Result.error("批量分配车辆失败: " + e.getMessage());
        }
    }

    @GetMapping("/statistics")
    @Operation(summary = "获取调度统计信息", description = "获取调度相关统计数据")
    public Result<DispatchStatisticsVO> getDispatchStatistics() {
        try {
            DispatchStatisticsVO result = dispatchService.getDispatchStatistics();
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取调度统计信息失败: {}", e.getMessage(), e);
            return Result.error("获取调度统计信息失败: " + e.getMessage());
        }
    }

    @PostMapping("/smart-match")
    @Operation(summary = "智能匹配调度", description = "根据条件智能匹配合适的调度")
    public Result<String> smartMatchDispatches(
            @Parameter(description = "匹配条件") @RequestParam String matchCriteria,
            @Parameter(description = "最大匹配数量") @RequestParam(defaultValue = "10") Integer maxMatches) {
        try {
            String result = dispatchService.smartMatchDispatches(matchCriteria, maxMatches);
            return Result.success(result);
        } catch (Exception e) {
            log.error("智能匹配调度失败: {}", e.getMessage(), e);
            return Result.error("智能匹配调度失败: " + e.getMessage());
        }
    }

    @GetMapping("/pending")
    @Operation(summary = "获取待处理调度列表", description = "获取待处理的调度列表")
    public Result<List<Dispatch>> getPendingDispatches(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        try {
            List<Dispatch> result = dispatchService.getPendingDispatches(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取待处理调度列表失败: {}", e.getMessage(), e);
            return Result.error("获取待处理调度列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/in-progress")
    @Operation(summary = "获取进行中调度列表", description = "获取正在进行的调度列表")
    public Result<List<Dispatch>> getInProgressDispatches(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        try {
            List<Dispatch> result = dispatchService.getInProgressDispatches(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取进行中调度列表失败: {}", e.getMessage(), e);
            return Result.error("获取进行中调度列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/completed")
    @Operation(summary = "获取已完成调度列表", description = "获取已完成的调度列表")
    public Result<List<Dispatch>> getCompletedDispatches(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        try {
            List<Dispatch> result = dispatchService.getCompletedDispatches(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取已完成调度列表失败: {}", e.getMessage(), e);
            return Result.error("获取已完成调度列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/urgent")
    @Operation(summary = "获取紧急调度列表", description = "获取紧急的调度列表")
    public Result<List<Dispatch>> getUrgentDispatches(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "30") Integer limit) {
        try {
            List<Dispatch> result = dispatchService.getUrgentDispatches(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取紧急调度列表失败: {}", e.getMessage(), e);
            return Result.error("获取紧急调度列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/high-priority")
    @Operation(summary = "获取高优先级调度列表", description = "获取高优先级的调度列表")
    public Result<List<Dispatch>> getHighPriorityDispatches(
            @Parameter(description = "最低优先级") @RequestParam(defaultValue = "8") Integer minPriority,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "30") Integer limit) {
        try {
            List<Dispatch> result = dispatchService.getHighPriorityDispatches(minPriority, limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取高优先级调度列表失败: {}", e.getMessage(), e);
            return Result.error("获取高优先级调度列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/overdue")
    @Operation(summary = "获取逾期调度列表", description = "获取逾期的调度列表")
    public Result<List<Dispatch>> getOverdueDispatches(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "30") Integer limit) {
        try {
            List<Dispatch> result = dispatchService.getOverdueDispatches(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取逾期调度列表失败: {}", e.getMessage(), e);
            return Result.error("获取逾期调度列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/today")
    @Operation(summary = "获取今日调度列表", description = "获取今日的调度列表")
    public Result<List<Dispatch>> getTodayDispatches(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "100") Integer limit) {
        try {
            List<Dispatch> result = dispatchService.getTodayDispatches(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取今日调度列表失败: {}", e.getMessage(), e);
            return Result.error("获取今日调度列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/by-driver/{driverId}")
    @Operation(summary = "根据司机ID获取调度列表", description = "获取指定司机的调度列表")
    public Result<List<Dispatch>> getDispatchesByDriver(
            @Parameter(description = "司机ID") @PathVariable Long driverId,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        try {
            List<Dispatch> result = dispatchService.getDispatchesByDriver(driverId, limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("根据司机ID获取调度列表失败: {}", e.getMessage(), e);
            return Result.error("根据司机ID获取调度列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/by-vehicle/{vehicleId}")
    @Operation(summary = "根据车辆ID获取调度列表", description = "获取指定车辆的调度列表")
    public Result<List<Dispatch>> getDispatchesByVehicle(
            @Parameter(description = "车辆ID") @PathVariable Long vehicleId,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        try {
            List<Dispatch> result = dispatchService.getDispatchesByVehicle(vehicleId, limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("根据车辆ID获取调度列表失败: {}", e.getMessage(), e);
            return Result.error("根据车辆ID获取调度列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/by-route/{routeId}")
    @Operation(summary = "根据路线ID获取调度列表", description = "获取指定路线的调度列表")
    public Result<List<Dispatch>> getDispatchesByRoute(
            @Parameter(description = "路线ID") @PathVariable Long routeId,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        try {
            List<Dispatch> result = dispatchService.getDispatchesByRoute(routeId, limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("根据路线ID获取调度列表失败: {}", e.getMessage(), e);
            return Result.error("根据路线ID获取调度列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/check/exists/{id}")
    @Operation(summary = "检查调度是否存在", description = "根据ID检查调度是否存在")
    public Result<Boolean> checkDispatchExists(@Parameter(description = "调度ID") @PathVariable Long id) {
        try {
            boolean result = dispatchService.checkDispatchExists(id);
            return Result.success(result);
        } catch (Exception e) {
            log.error("检查调度是否存在失败: {}", e.getMessage(), e);
            return Result.error("检查调度是否存在失败: " + e.getMessage());
        }
    }

    @GetMapping("/check/code")
    @Operation(summary = "检查调度编码是否存在", description = "检查调度编码是否已被使用")
    public Result<Boolean> checkDispatchCodeExists(
            @Parameter(description = "调度编码") @RequestParam String dispatchCode,
            @Parameter(description = "排除的调度ID") @RequestParam(required = false) Long excludeId) {
        try {
            boolean result = dispatchService.checkDispatchCodeExists(dispatchCode, excludeId);
            return Result.success(result);
        } catch (Exception e) {
            log.error("检查调度编码是否存在失败: {}", e.getMessage(), e);
            return Result.error("检查调度编码是否存在失败: " + e.getMessage());
        }
    }

    @PutMapping("/start/{id}")
    @Operation(summary = "开始调度", description = "开始执行调度任务")
    public Result<Boolean> startDispatch(
            @Parameter(description = "调度ID") @PathVariable Long id,
            @Parameter(description = "开始人ID") @RequestParam Long startedBy) {
        try {
            boolean result = dispatchService.startDispatch(id, startedBy);
            return result ? Result.success(true) : Result.error("开始调度失败");
        } catch (Exception e) {
            log.error("开始调度失败: {}", e.getMessage(), e);
            return Result.error("开始调度失败: " + e.getMessage());
        }
    }

    @PutMapping("/complete/{id}")
    @Operation(summary = "完成调度", description = "完成调度任务")
    public Result<Boolean> completeDispatch(
            @Parameter(description = "调度ID") @PathVariable Long id,
            @Parameter(description = "完成备注") @RequestParam(required = false) String completionNotes,
            @Parameter(description = "完成人ID") @RequestParam Long completedBy) {
        try {
            boolean result = dispatchService.completeDispatch(id, completionNotes, completedBy);
            return result ? Result.success(true) : Result.error("完成调度失败");
        } catch (Exception e) {
            log.error("完成调度失败: {}", e.getMessage(), e);
            return Result.error("完成调度失败: " + e.getMessage());
        }
    }

    @PutMapping("/cancel/{id}")
    @Operation(summary = "取消调度", description = "取消调度任务")
    public Result<Boolean> cancelDispatch(
            @Parameter(description = "调度ID") @PathVariable Long id,
            @Parameter(description = "取消原因") @RequestParam String cancelReason,
            @Parameter(description = "取消人ID") @RequestParam Long cancelledBy) {
        try {
            boolean result = dispatchService.cancelDispatch(id, cancelReason, cancelledBy);
            return result ? Result.success(true) : Result.error("取消调度失败");
        } catch (Exception e) {
            log.error("取消调度失败: {}", e.getMessage(), e);
            return Result.error("取消调度失败: " + e.getMessage());
        }
    }

    @PutMapping("/pause/{id}")
    @Operation(summary = "暂停调度", description = "暂停调度任务")
    public Result<Boolean> pauseDispatch(
            @Parameter(description = "调度ID") @PathVariable Long id,
            @Parameter(description = "暂停原因") @RequestParam String pauseReason,
            @Parameter(description = "暂停人ID") @RequestParam Long pausedBy) {
        try {
            boolean result = dispatchService.pauseDispatch(id, pauseReason, pausedBy);
            return result ? Result.success(true) : Result.error("暂停调度失败");
        } catch (Exception e) {
            log.error("暂停调度失败: {}", e.getMessage(), e);
            return Result.error("暂停调度失败: " + e.getMessage());
        }
    }

    @PutMapping("/resume/{id}")
    @Operation(summary = "恢复调度", description = "恢复暂停的调度任务")
    public Result<Boolean> resumeDispatch(
            @Parameter(description = "调度ID") @PathVariable Long id,
            @Parameter(description = "恢复人ID") @RequestParam Long resumedBy) {
        try {
            boolean result = dispatchService.resumeDispatch(id, resumedBy);
            return result ? Result.success(true) : Result.error("恢复调度失败");
        } catch (Exception e) {
            log.error("恢复调度失败: {}", e.getMessage(), e);
            return Result.error("恢复调度失败: " + e.getMessage());
        }
    }

    @PutMapping("/assign-driver/{id}")
    @Operation(summary = "分配司机", description = "为调度分配司机")
    public Result<Boolean> assignDriver(
            @Parameter(description = "调度ID") @PathVariable Long id,
            @Parameter(description = "司机ID") @RequestParam Long driverId,
            @Parameter(description = "分配人ID") @RequestParam Long assignedBy) {
        try {
            boolean result = dispatchService.assignDriver(id, driverId, assignedBy);
            return result ? Result.success(true) : Result.error("分配司机失败");
        } catch (Exception e) {
            log.error("分配司机失败: {}", e.getMessage(), e);
            return Result.error("分配司机失败: " + e.getMessage());
        }
    }

    @PutMapping("/assign-vehicle/{id}")
    @Operation(summary = "分配车辆", description = "为调度分配车辆")
    public Result<Boolean> assignVehicle(
            @Parameter(description = "调度ID") @PathVariable Long id,
            @Parameter(description = "车辆ID") @RequestParam Long vehicleId,
            @Parameter(description = "分配人ID") @RequestParam Long assignedBy) {
        try {
            boolean result = dispatchService.assignVehicle(id, vehicleId, assignedBy);
            return result ? Result.success(true) : Result.error("分配车辆失败");
        } catch (Exception e) {
            log.error("分配车辆失败: {}", e.getMessage(), e);
            return Result.error("分配车辆失败: " + e.getMessage());
        }
    }

    @PutMapping("/update-progress/{id}")
    @Operation(summary = "更新调度进度", description = "更新调度任务的执行进度")
    public Result<Boolean> updateDispatchProgress(
            @Parameter(description = "调度ID") @PathVariable Long id,
            @Parameter(description = "进度百分比") @RequestParam Integer progressPercentage,
            @Parameter(description = "进度描述") @RequestParam(required = false) String progressDescription,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = dispatchService.updateDispatchProgress(id, progressPercentage, progressDescription, updatedBy);
            return result ? Result.success(true) : Result.error("更新调度进度失败");
        } catch (Exception e) {
            log.error("更新调度进度失败: {}", e.getMessage(), e);
            return Result.error("更新调度进度失败: " + e.getMessage());
        }
    }

    @PostMapping("/auto-assign")
    @Operation(summary = "自动分配调度", description = "根据算法自动分配调度任务")
    public Result<Boolean> autoAssignDispatch(
            @Parameter(description = "调度ID") @RequestParam Long dispatchId,
            @Parameter(description = "分配策略") @RequestParam(defaultValue = "OPTIMAL") String assignmentStrategy,
            @Parameter(description = "分配人ID") @RequestParam Long assignedBy) {
        try {
            boolean result = dispatchService.autoAssignDispatch(dispatchId, assignmentStrategy, assignedBy);
            return result ? Result.success(true) : Result.error("自动分配调度失败");
        } catch (Exception e) {
            log.error("自动分配调度失败: {}", e.getMessage(), e);
            return Result.error("自动分配调度失败: " + e.getMessage());
        }
    }

    @PostMapping("/optimize-route/{id}")
    @Operation(summary = "优化调度路线", description = "优化调度任务的执行路线")
    public Result<Boolean> optimizeDispatchRoute(
            @Parameter(description = "调度ID") @PathVariable Long id,
            @Parameter(description = "优化参数") @RequestParam String optimizationParams,
            @Parameter(description = "优化人ID") @RequestParam Long optimizedBy) {
        try {
            boolean result = dispatchService.optimizeDispatchRoute(id, optimizationParams, optimizedBy);
            return result ? Result.success(true) : Result.error("优化调度路线失败");
        } catch (Exception e) {
            log.error("优化调度路线失败: {}", e.getMessage(), e);
            return Result.error("优化调度路线失败: " + e.getMessage());
        }
    }

}